//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<expose_ui_to_python.cpp>
///	@path	~/src/python/wrap/
///	@date	2008/09/10
///	@brief	.

#include "python_pre.h"

#include "lib/utilities/observer.h"

#include "gui/style/style.h"
#include "gui/style/ext_style.h"
#include "gui/IGuiComp.h"
#include "gui/IGuiControl.h"
#include "gui/IGuiForm.h"
#include "gui/image/IBitmap.h"
#include "gui/image/ImageResource.h"
#include "gui/xgui/XForm.h"
#include "gui/xgui/XFrame.h"
#include "gui/xgui/XPanel.h"
#include "gui/xgui/XPopup.h"
#include "gui/xgui/XCtrls.h"
#include "gui/xgui/XEditCtrl.h"
#include "gui/xgui/XCtrlsExt.h"
#include "gui/xgui/XDesktop.h"

using namespace xeres;

#include "python/wrap/expose_decl_python.h"

namespace xeres {

	namespace {

		//////////////////////////////////////////////////////////////////////////
		// Object basic attributes

		// Font representation.
		std::string StyleFontRepr( StyleFont * font )
		{
			char buf[256];
			sprintf( buf , "<xeres.StyleFont object (face:\"%S\" height:%u weight:%u %s %s)>" ,
				font->GetName().c_str() , font->GetLogicHeight() , font->GetWeight() ,
				font->GetItalic() ? "italic" : "regular" , font->GetAntialias() ? "antialiased" : "" );
			return buf;
		}
		// Gui component representation.
		std::string IGuiCompRepr( IGuiComp * comp )
		{
			char buf[256];
			sprintf( buf , "<xeres.%S object (id:%u)>" , comp->GetClassName().c_str() , comp->GetId() );
			return buf;
		}
		// Image representation.
		std::string IBitmapRepr( IBitmap * bmp )
		{
			char buf[256];
			sprintf( buf , "<xeres.%S object (addr:%u width:%u height:%u)>" , bmp , bmp->GetWidth() , bmp->GetHeight() );
			return buf;
		}

		// Visible determination.
		bool IsVisible( IGuiComp * comp )
		{
			if( !comp->GetVisible() )
				return false;
			RefWeak<IGuiForm> parent = comp->GetParent();
			while( parent.IsValid() )
			{
				if( !parent->GetVisible() )
					return false;
				parent = parent->GetParent();
			}
			return true;
		}

		//////////////////////////////////////////////////////////////////////////
		// Basic calling wrap.

		// Wrap add child function for bind.
		bool IGuiFormAddChildWrap( IGuiForm * form , IGuiComp * child )
		{
			Ref<IGuiComp> comp( child );
			return form->AddChild( comp );
		}
		// Wrap del child function for bind.
		bool IGuiFormDelChildWrap( IGuiForm * form , IGuiComp * child )
		{
			Ref<IGuiComp> comp( child );
			return form->DelChild( comp );
		}
		// Wrap request focus function for bind.
		void IGuiFormReqFocusWrap( IGuiForm * form , IGuiComp * child )
		{
			Ref<IGuiComp> comp( child );
			form->RequestFocus( comp );
		}
		// Wrap clear focus function for bind.
		void IGuiFormClearFocusWrap( IGuiForm * form )
		{
			form->ClearFocus();
		}
		// Wrap get children for bind.
		boost::python::list IGuiFormGetChildrenWrap( IGuiForm * form )
		{
			boost::python::list comps;
			for( int i = 0 ; ; ++i )
			{
				RefWeak<IGuiComp> comp = form->GetChild( i );
				if( comp.IsNull() )
					break;
				comps.append( Ref<IGuiComp>( comp ) );
			}
			return comps;
		}
		// Wrap get parent function for bind.
		Ref<IGuiForm> IGuiCompGetParentWrap( IGuiComp * comp )
		{
			return Ref<IGuiForm>( comp->GetParent() );
		}
		// Wrap get style function for bind.
		template<typename _Type> Ref<IStyle> _GetStyleWrap( _Type * comp )
		{
			return comp->GetStyle();
		}
		// Wrap get background for bind.
		template<typename _Type> Ref<IBitmap> _GetBackgroundWrap( _Type * comp )
		{
			return comp->GetBackground();
		}
		// Wrap set background for bind.
		template<typename _Type> void _SetBackgroundWrap( _Type * comp , IBitmap * background )
		{
			comp->SetBackground( background );
		}
		
		// Wrap set background with edge for bind.
		template<typename _Type> void _SetBackgroundEdgeWrap( _Type * comp , boost::python::tuple p )
		{
			int len = extract<int>( p.attr("__len__")() );
			Ref<IBitmap> background = extract< Ref<IBitmap> >( p[0] );
			if( len == 1 )
			{
				comp->SetBackground( background , Pair<int>( -1 , -1 ) );
			}
			else if( len == 2 )
			{
				Pair<int> edge = extract< Pair<int> >( p[1] );
				comp->SetBackground( background , edge );
			}
			else if( len == 3 )
			{
				int x = extract< int >( p[1] );
				int y = extract< int >( p[2] );
				comp->SetBackground( background , Pair<int>( x , y ) );
			}
			else
			{
				PyErr_SetString( PyExc_ValueError, "Background-with-edge attribute count mismatch" );
				throw( error_already_set() );
			}
		}
		// Wrap set text function for bind.
		void XEditCtrlSetTextWrap1( XEditCtrl * edit , const WString& text )
		{
			edit->SetText( text , false );
		}
		// Wrap set text function for bind.
		void XEditCtrlSetTextWrap2( XEditCtrl * edit , const WString& text , bool select )
		{
			edit->SetText( text , select );
		}
		// Wrap show window function for bind.
		void XDesktopShowWindowWrap1( XDesktop * desktop , XFrame * frame , bool hide )
		{
			desktop->ShowWindow( frame , hide , true );
		}
		// Wrap show window function for bind.
		void XDesktopShowWindowWrap2( XDesktop * desktop , XFrame * frame , bool hide , bool animate )
		{
			desktop->ShowWindow( frame , hide , animate );
		}
		// Wrap track tips.
		void XDesktopTrackTipsWrap( XDesktop * desktop , IGuiComp * comp , const WString& tips )
		{
			desktop->TrackTips( comp , tips );
		}
		// Wrap attach function for bind.
		void XDesktopAttachWrap( XDesktop * desktop , XFrame * frame )
		{
			desktop->Attach( frame );
		}
		// Wrap attach function for bind.
		void XDesktopDetachWrap( XDesktop * desktop , XFrame * frame )
		{
			desktop->Detach( frame );
		}

		//////////////////////////////////////////////////////////////////////////
		// Resource wrap calls.
		// Font getter & setter wrap.
		Ref<StyleFont> GetFontWrap( TextStyle * style )
		{
			return style->m_font;
		}
		void SetFontWrap( TextStyle * style , Ref<StyleFont> fnt )
		{
			style->m_font = fnt;
		}
		// Wrap to create image for bind.
		Ref<IBitmap> ImageResourceLoadWrap1( ImageResource * res , const WString& resource )
		{
			return res->LoadImage( resource );
		}
		// Wrap to create image for bind.
		Ref<IBitmap> ImageResourceLoadWrap2( ImageResource * res , const WString& resource , int frame )
		{
			return res->LoadImage( resource , frame );
		}
		// Wrap to create image for bind.
		Ref<IBitmap> ImageResourceLoadWrap3( ImageResource * res , const WString& resource , int frame , int starts )
		{
			return res->LoadImage( resource , frame , starts );
		}
		// Wrap to get image for bind.
		template< class _Type > Ref<IBitmap> _getImageWrap( _Type * comp )
		{
			return comp->GetImage();
		}
		// Wrap to get image for bind.
		template< class _Type > void _setImageWrap( _Type * comp , IBitmap * bitmap )
		{
			return comp->SetImage( bitmap );
		}

		Ref<IGuiComp> IGuiFormGetFocusingWrap( IGuiForm * form )
		{
			return form->GetFocusing();
		}

		//////////////////////////////////////////////////////////////////////////
		// Child iterator.
		class IGuiFormChildIter
		{
		public:
			/// \ctor
			IGuiFormChildIter( RefWeak<IGuiForm> form ) : m_index( 0 ) , m_form( form ) {}

			/// \ctor
			IGuiFormChildIter( const IGuiFormChildIter& rhs ) : m_index( rhs.m_index ) , m_form( rhs.m_form ) {}

			/// \next
			object next( void )
			{
				RefWeak<IGuiComp> comp = m_form->GetChild( m_index );
				if( comp.IsValid() )
					return object( Ref<IGuiComp>( comp ) );
				else
				{
					PyErr_SetString( PyExc_StopIteration , "No more data." );
					boost::python::throw_error_already_set();
					return object();
				}
			}

		private:

			// @data
			int m_index;
			Ref<IGuiForm> m_form;
		};

		// Generate iterator.
		IGuiFormChildIter IGuiFormGenChildIter( IGuiForm * form )
		{
			return IGuiFormChildIter( form );
		}

		//////////////////////////////////////////////////////////////////////////
		// Event wrap.

		// Get callback function wrap.
		object GetCallBackWrap( IGuiComp * comp )
		{
			return object();
		}

		// General key input event wrap.
		bool _keyWrap( int status , KeyInput::Key key , bool pressed , object func )
		{
			bool res = false;
			try
			{
				res = func( make_tuple( status , key , pressed ) );
			}
			catch( error_already_set )
			{
				PyErr_Print();
				PyErr_Clear();
			}
			return res;
		}

		// General mouse click event wrap.
		void _clickWrap( object func )
		{
			try
			{
				func();
			}
			catch( error_already_set )
			{
				PyErr_Print();
				PyErr_Clear();
			}
		}
		// Mouse hover event wrap.
		void _hoverWrap( object func )
		{
			try
			{
				func();
			}
			catch( error_already_set )
			{
				PyErr_Print();
				PyErr_Clear();
			}
		}
		// General default event wrap.
		bool _defaultWrap( bool ok , object func )
		{
			bool res = false;
			try
			{
				res = func( ok );
			}
			catch( error_already_set )
			{
				PyErr_Print();
				PyErr_Clear();
			}
			return res;
		}
		// General notify event wrap.
		void _notifyWrap( object func )
		{
			try
			{
				func();
			}
			catch( error_already_set )
			{
				PyErr_Print();
				PyErr_Clear();
			}
		}
		// General SetOnClick call wrap.
		template< class _Type > void _setOnClickWrap( _Type * comp  , object func )
		{
			if( !PyCallable_Check( func.ptr() ) )
			{
				PyErr_SetString( PyExc_ValueError, "Object is not callable." );
				boost::python::throw_error_already_set();
			}
			comp->SetOnClick( bind( _clickWrap , func ) );
		}
		// General SetOnHover call wrap.
		template< class _Type > void _setOnHoverWrap( _Type * comp  , object func )
		{
			if( !PyCallable_Check( func.ptr() ) )
			{
				PyErr_SetString( PyExc_ValueError, "Object is not callable." );
				boost::python::throw_error_already_set();
			}
			comp->SetOnHover( bind( _hoverWrap , func ) );
		}
		// General SetOnDefault call wrap.
		template< class _Type > void _setOnDefaultWrap( _Type * comp , object func )
		{
			if( !PyCallable_Check( func.ptr() ) )
			{
				PyErr_SetString( PyExc_ValueError, "Object is not callable." );
				boost::python::throw_error_already_set();
			}
			comp->SetOnDefault( bind( _defaultWrap , _1 , func ) );
		}
		template< class _Type > void _setOnTextWrap( _Type * comp , object func )
		{
			if( !PyCallable_Check( func.ptr() ) )
			{
				PyErr_SetString( PyExc_ValueError, "Object is not callable." );
				boost::python::throw_error_already_set();
			}
			comp->SetOnText( bind( _notifyWrap , func ) );
		}
		template< class _Type > void _setOnKeyWrap( _Type * comp , object func )
		{
			if( !PyCallable_Check( func.ptr() ) )
			{
				PyErr_SetString( PyExc_ValueError, "Object is not callable." );
				boost::python::throw_error_already_set();
			}
			comp->SetOnKey( bind( _keyWrap , _1 , _2 , _3 , func ) );
		}

		//////////////////////////////////////////////////////////////////////////
		// Constructor with events.

		// XButton constructor.
		Ref<XButton> XButtonConstructorWrap( const WString& label , const Rect<int>& placement , object func )
		{
			return Ref<XButton>( new XButton( label , placement , bind( _clickWrap , func ) ) );
		}

		//////////////////////////////////////////////////////////////////////////
		// Frame constructions.
		// Create frames by class name.
		Ref<XFrame> XFrameConstructorWrap1( const WString& _class )
		{
			Ref<XFrame> frame = ObjectFactory::CreateObject( _class );
			return frame;
		}
		Ref<XFrame> XFrameConstructorWrap2( const WString& _class , const Rect<int>& rect )
		{
			Ref<XFrame> frame = ObjectFactory::CreateObject( _class );
			frame->SetPlacement( rect );
			return frame;
		}
		Ref<XFrame> XFrameConstructorWrap3( const WString& _class , const Pair<int>& pos )
		{
			Ref<XFrame> frame = ObjectFactory::CreateObject( _class );
			frame->SetPosition( pos );
			return frame;
		}
	}

	// expose ui
	static void expose_comp( void )
	{
		//////////////////////////////////////////////////////////////////////////
		// Basic elements & resources.

		// Text alignment.
		enum_<PlacementStyle::ALIGNMENT>("StyleAlignment")
			.value("left",PlacementStyle::LEFT)
			.value("middle",PlacementStyle::MIDDLE)
			.value("right",PlacementStyle::RIGHT)
			.value("top",PlacementStyle::TOP)
			.value("center",PlacementStyle::CENTER)
			.value("bottom",PlacementStyle::BOTTOM)
		;

		// Text decoration.
		enum_<TextStyle::DECORATION>("TextDecoration")
			.value("none",TextStyle::DECORATION_NONE)
			.value("underline",TextStyle::UNDERLINE)
			.value("overline",TextStyle::OVERLINE)
			.value("bothline",TextStyle::BOTHLINE)
			.value("line_through",TextStyle::LINE_THROUGH)
		;

		// Text transform.
		enum_<TextStyle::LETTER>("TextTransform")
			.value("normal",TextStyle::LETTER_NORMAL)
			.value("capitalize",TextStyle::CAPITALIZE)
			.value("lowercase",TextStyle::LOWERCASE)
			.value("uppercase",TextStyle::UPPERCASE)
		;

		// Style font.
		class_< StyleFont , Ref<StyleFont> , bases< IObject > , noncopyable >( "StyleFont" , no_init )
			// Object property.
			.add_property( "face" , make_function( &StyleFont::GetName , RET_COPYREF ) )
			.add_property( "logic_height" , &StyleFont::GetLogicHeight )
			.add_property( "pixel_height" , &StyleFont::GetFontHeight )
			.add_property( "weight" , &StyleFont::GetWeight )
			.add_property( "italic" , &StyleFont::GetItalic )
			.add_property( "antialias" , &StyleFont::GetAntialias )
			// Object attributes.
			.def( "__repr__" , &StyleFontRepr );
		;
		register_object_to_python<StyleFont>();
		def( "CreateFont" , &StyleFont::CreateFont );
		def( "QueryFont" , &StyleFont::QueryFont );
		def( "InstallFont" , &StyleFont::InstallFont );

		// Placement style.
		class_< PlacementStyle , noncopyable >( "PlacementStyle" , init<>() )
			.def( init<const PlacementStyle&>() )
			// Properties
			.def_readwrite( "horizontal_align" , &PlacementStyle::m_horizontal )
			.def_readwrite( "vertical_align" , &PlacementStyle::m_vertical )
			.def_readwrite( "padding" , &PlacementStyle::m_padding )
			.def_readwrite( "padding_left" , &PlacementStyle::m_padding_left )
			.def_readwrite( "paddnig_top" , &PlacementStyle::m_padding_top )
			.def_readwrite( "padding_right" , &PlacementStyle::m_padding_right )
			.def_readwrite( "padding_bottom" , &PlacementStyle::m_padding_bottom )
			.def_readwrite( "margin" , &PlacementStyle::m_margin )
			.def_readwrite( "margin_left" , &PlacementStyle::m_margin_left )
			.def_readwrite( "margin_top" , &PlacementStyle::m_margin_top )
			.def_readwrite( "margin_right" , &PlacementStyle::m_margin_right )
			.def_readwrite( "margin_bottom" , &PlacementStyle::m_margin_bottom )
		;

 		// Text style.
		class_< TextStyle , noncopyable >( "TextStyle" , init<>() )
			.def( init<const TextStyle&>() )
			// Properties
			.add_property( "font" , &GetFontWrap , &SetFontWrap )
			.def_readwrite( "text_color" , &TextStyle::m_textColor )
			.def_readwrite( "text_edge_color" , &TextStyle::m_edgeColor )
			.def_readwrite( "text_shadow_color" , &TextStyle::m_shadowColor )
			.def_readwrite( "text_background_color" , &TextStyle::m_textBackColor )
			.def_readwrite( "text_decoration" , &TextStyle::m_decoration )
			.def_readwrite( "line_height" , &TextStyle::m_lineHeight )
			.def_readwrite( "text_indent" , &TextStyle::m_textIndent )
			.def_readwrite( "text_offset" , &TextStyle::m_textOffset )
			.def_readwrite( "letter_spacing" , &TextStyle::m_textLetterSpacing )
			.def_readwrite( "word_spacing" , &TextStyle::m_textWordSpacing )
			.def_readwrite( "text_transform" , &TextStyle::m_textTransform )
 		;
		register_ptr_to_python< TextStyle* >();

		// Image style.
		class_< ImageStyle >( "ImageStyle" , init<>() )
			.def( init<const ImageStyle&>() )
			// Properties
			.add_property( "image_tint" , &ImageStyle::m_tint )
			.add_property( "image_border_color" , &ImageStyle::m_borderColor )
		;
		register_ptr_to_python< ImageStyle* >();

		// Gui style.
		class_< GuiStyle >( "GuiStyle" , init<>() )
			.def( init<const GuiStyle&>() )
			// Properties
			.def_readwrite( "gui_background_color" , &GuiStyle::m_guiBackgroundColor )
			.def_readwrite( "gui_border_color" , &GuiStyle::m_guiBorderColor )
		;
		register_ptr_to_python< GuiStyle* >();

		// Image resources.
		class_< IBitmap , bases< IObject > , noncopyable >( "IBitmap" , no_init )
			// Object property.
			.add_property( "size" , &IBitmap::GetSize )
			.add_property( "storage_size" , &IBitmap::GetStorageSize )
			.add_property( "frames" , &IBitmap::GetFrame )
			// Methods.
			.def( "GetPixel" , &IBitmap::GetPixel )
		;
		register_ptr_to_python< Ref<IBitmap> >();
		register_object_to_python<IBitmap>();

		class_< ImageResource , noncopyable >( "LoadImage" , no_init )
			.def( "__call__" , &ImageResourceLoadWrap1 )
			.def( "__call__" , &ImageResourceLoadWrap2 )
			.def( "__call__" , &ImageResourceLoadWrap3 )
		;
		register_ptr_to_python< eternal_ptr< ImageResource > >();

		// Style.
		class_< IStyle , bases<IObject> , noncopyable >( "IStyle" , no_init )
		;
		register_ptr_to_python< Ref<IStyle> >();
		register_object_to_python<IStyle>();

		// CTextStyle
		class_< CTextStyle , Ref<CTextStyle> , bases<IStyle,PlacementStyle,TextStyle> , noncopyable >( "CTextStyle" , no_init )
		;
		register_object_to_python<CTextStyle>();

		// CGuiStyle
		class_< CGuiStyle , Ref<CGuiStyle> , bases<CTextStyle,ImageStyle,GuiStyle> , noncopyable >( "CGuiStyle" , no_init )
			.add_property( "focus" , &CGuiStyle::AccessFocus )
			.add_property( "active" , &CGuiStyle::AccessFocus )
			.add_property( "hover" , &CGuiStyle::AccessHover )
			.add_property( "clicked" , &CGuiStyle::AccessClicked )
			.add_property( "enable" , &CGuiStyle::AccessEnable )
			.add_property( "disable" , &CGuiStyle::AccessDisable )
		;
		register_object_to_python<CGuiStyle>();

		//////////////////////////////////////////////////////////////////////////
		// Interface.

		class_< IGuiComp , bases< IObject > , noncopyable >( "IGuiComp" , no_init )
			// Object property
			.add_property( "parent" , &IGuiCompGetParentWrap )
			.add_property( "position" , &IGuiComp::GetPosition , &IGuiComp::SetPosition )
			.add_property( "size" , &IGuiComp::GetSize , &IGuiComp::SetSize )
			.add_property( "enable" , &IGuiComp::GetEnable , &IGuiComp::SetEnable )
			.add_property( "visible" , &IGuiComp::GetVisible , &IGuiComp::SetVisible )
			.add_property( "focus" , &IGuiComp::GetFocus )
			// Methods.
			.def( "GetParent" , &IGuiCompGetParentWrap )
			.def( "GetPosition" , &IGuiComp::GetPosition )
			.def( "SetPosition" , &IGuiComp::SetPosition )
			.def( "GetSize" , &IGuiComp::GetSize )
			.def( "SetSize" , &IGuiComp::SetSize )
			.def( "GetPlacement" , &IGuiComp::GetPlacement )
			.def( "SetPlacement" , &IGuiComp::SetPlacement )
			.def( "GetEnable" , &IGuiComp::GetEnable )
			.def( "SetEnable" , &IGuiComp::SetEnable )
			.def( "GetVisible" , &IGuiComp::GetVisible )
			.def( "SetVisible" , &IGuiComp::SetVisible )
			.def( "GetFocus" , &IGuiComp::GetFocus )
			.def( "GetId" , &IGuiComp::GetId )
			.def( "BringToFront" , &IGuiComp::BringToFront )
			.def( "Close" , &IGuiComp::Close )
			.def( "IsVisible" , &IsVisible )
			// Object attributes.
			.def( "__repr__" , &IGuiCompRepr )
		;
		register_ptr_to_python< Ref<IGuiComp> >();
		register_object_to_python<IGuiComp>();

		class_< IGuiControl , bases< IGuiComp > , noncopyable >( "IGuiControl" , no_init )
			// Object property
			.add_property( "bound" , &IGuiControl::GetBound )
			// Methods.
			.def( "EnableActiveOrder" , &IGuiControl::EnableActiveOrder )
		;
		register_ptr_to_python< Ref<IGuiControl> >();
		register_object_to_python<IGuiControl>();

		boost::python::iterator_wrappers<IGuiFormChildIter>::wrap("IGuiFormIterator");
		class_< IGuiForm , bases< IGuiControl > , noncopyable >( "IGuiForm" , no_init )
			// Iterator
			.add_property( "children" , &IGuiFormGenChildIter )
			// Object property.
			.add_property( "focusing" , &IGuiFormGetFocusingWrap )
			// Methods.
			.def( "AddChild" , &IGuiFormAddChildWrap )
			.def( "DelChild" , &IGuiFormDelChildWrap )
			.def( "RequestFocus" , &IGuiFormReqFocusWrap )
			.def( "ClearFocus" , &IGuiFormClearFocusWrap )
			.def( "ListChildren" , &IGuiFormGetChildrenWrap )
		;
		register_ptr_to_python< Ref<IGuiForm> >();
		register_object_to_python<IGuiForm>();

		class_< IScrollBar , bases< IGuiControl > , noncopyable >( "IScrollBar" , no_init )
		;
		register_ptr_to_python< Ref< IScrollBar > >();
		register_object_to_python< IScrollBar >();

		class_< IScrollBarVertical , bases< IScrollBar > , noncopyable >( "IScrollBarVertical" , no_init )
		;
		register_ptr_to_python< Ref<IScrollBarVertical> >();
		register_object_to_python< IScrollBarVertical >();

		//////////////////////////////////////////////////////////////////////////
		// Controls.

		class_< XForm , Ref<XForm> , bases< IGuiForm > , noncopyable >( "XForm" , init<>() )
			.def( init<const Rect<int>&>() )
			.def( init<const Pair<int>&>() )
			// Methods.
		;
		register_object_to_python<XForm>();

		class_< XPanel , Ref<XPanel> , bases< XForm > , noncopyable >( "XPanel" , init<>() )
			.def( init<const Rect<int>&>() )
			.def( init<const Pair<int>&>() )
			.def( init< IBitmap* >() )
			// Object property
			.add_property( "style" , &_GetStyleWrap<XPanel> )
			.add_property( "background" , &_GetBackgroundWrap<XPanel> , &_SetBackgroundEdgeWrap<XPanel> )
			.add_property( "edge_size" , &XPanel::GetEdgeSize , &XPanel::SetEdgeSize )
			// Methods.
			.def( "GetBackground" , &_GetBackgroundWrap<XPanel> )
			.def( "SetBackground" , &_SetBackgroundWrap<XPanel> )
			.def( "GetEdgeSize" , &XPanel::GetEdgeSize )
			.def( "SetEdgeSize" , &XPanel::SetEdgeSize )
		;
		register_object_to_python<XPanel>();

		class_< XScrollPanel , Ref<XScrollPanel> , bases< XPanel > , noncopyable >( "XScrollPanel" , init<>() )
			.def( init<const Rect<int>&>() )
			.def( init<const Pair<int>&>() )
			.def( init< IBitmap* >() )
		;
		register_object_to_python<XScrollPanel>();

		class_< XFrame , Ref<XFrame> , bases< XPanel > , noncopyable >( "XFrame" , init<>() )
			.def( init<const Rect<int>&>() )
			.def( init<const Pair<int>&>() )
			.def( "__init__" , make_constructor( &XFrameConstructorWrap1 ) )
  			.def( "__init__" , make_constructor( &XFrameConstructorWrap2 ) )
  			.def( "__init__" , make_constructor( &XFrameConstructorWrap3 ) )
			// Object property.
			.add_property( "edge" , make_function( &XFrame::GetFrameEdge , RET_COPYREF ) , &XFrame::SetFrameEdge )
			// Methods.
		;
		register_object_to_python<XFrame>();

		class_< XLabel , Ref<XLabel> , bases< IGuiControl > , noncopyable >( "XLabel" , init<>() )
			.def( init<const WString& , const Rect<int>& >() )
			// Object property.
			.add_property( "text" , make_function( &XLabel::GetText , RET_COPYREF ) , &XLabel::SetText )
			.add_property( "style" , &_GetStyleWrap<XLabel> )
			// Methods.
			.def( "SetText" , &XLabel::SetText )
			.def( "GetText" , &XLabel::GetText , RET_COPYREF )
		;
		register_object_to_python<XLabel>();

		class_< XTextBlock , Ref<XTextBlock> , bases< IGuiControl > , noncopyable >( "XTextBlock" , init<>() )
			.def( init<const WString& , const Rect<int>& >() )
			// Object property.
			.add_property( "text" , make_function( &XTextBlock::GetText , RET_COPYREF ) , &XTextBlock::SetText )
			.add_property( "style" , &_GetStyleWrap<XTextBlock> )
			// Methods.
			.def( "SetText" , &XTextBlock::SetText )
			.def( "GetText" , &XTextBlock::GetText , RET_COPYREF )
		;
		register_object_to_python<XTextBlock>();

		class_< XClickLabel , Ref<XClickLabel> , bases< XLabel > , noncopyable >( "XClickLabel" , init<>() )
			.def( init<const WString& , const Rect<int>& >() )
			// Events
			.def( "SetOnClick" , &_setOnClickWrap<XClickLabel> )
		;
		register_object_to_python<XClickLabel>();

		class_< XButton , Ref<XButton> , bases< IGuiControl > , noncopyable >( "XButton" , init<>() )
			.def( init<const WString& , const Rect<int>&>() )
			.def( "__init__" , make_constructor( &XButtonConstructorWrap ) )
			// Object property.
			.add_property( "text" , make_function( &XButton::GetText , RET_COPYREF ) , &XButton::SetText )
			.add_property( "style" , &_GetStyleWrap<XButton> )
			.add_property( "on_click" , &GetCallBackWrap , &_setOnClickWrap<XButton> )
			// Method.
			// Events.
			.def( "SetOnClick" , &_setOnClickWrap<XButton> )
		;
		register_object_to_python<XButton>();

		class_< XSimpleButton , Ref<XSimpleButton> , bases< IGuiControl > , noncopyable >( "XSimpleButton" , init<>() )
			.def( init<const WString& , IBitmap* , const Pair<int>& >() )
			// Object property.
			.add_property( "text" , make_function( &XSimpleButton::GetText , RET_COPYREF ) , &XSimpleButton::SetText )
			.add_property( "image" , &_getImageWrap<XSimpleButton> , &_setImageWrap<XSimpleButton> )
			.add_property( "style" , &_GetStyleWrap<XSimpleButton> )
			.add_property( "on_click" , &GetCallBackWrap , &_setOnClickWrap<XSimpleButton> )
			// Methods.
			.def( "GetText" , &XSimpleButton::GetText , RET_COPYREF )
			.def( "SetText" , &XSimpleButton::SetText )
			.def( "GetImage" , &_getImageWrap<XSimpleButton> )
			.def( "SetImage" , &_setImageWrap<XSimpleButton> )
			// Events.
			.def( "SetOnClick" , &_setOnClickWrap<XSimpleButton> )
			.def( "SetOnHover" , &_setOnHoverWrap<XSimpleButton> )
			.def( "SetOnDefault" , &_setOnDefaultWrap<XSimpleButton> )
		;
		register_object_to_python<XSimpleButton>();

		class_< XClickButton , Ref<XClickButton> , bases< XSimpleButton > , noncopyable >( "XClickButton" , init<>() )
			.def( init<const WString& , IBitmap* , const Pair<int>& >() )
			// Object property.
			// Methods.
			// Events.
		;
		register_object_to_python<XClickButton>();

		class_< XEditCtrl , Ref<XEditCtrl> , bases< IGuiControl > , noncopyable >( "XEditCtrl" , init<>() )
			.def( init< const Rect<int>& , Ref<StyleFont> >() )
			// Object property.
			.add_property( "text" , make_function( &XEditCtrl::GetText , RET_COPYREF ) , &XEditCtrl::SetText )
			// Methods.
			.def( "GetText" , &XEditCtrl::GetText , RET_COPYREF )
			.def( "SetText" , &XEditCtrlSetTextWrap1 )
			.def( "SetText" , &XEditCtrlSetTextWrap2 )
			.def( "SetFont" , &XEditCtrl::SetFont )
			.def( "SetPassword" , &XEditCtrl::SetPassword )
			.def( "SelectAll" , &XEditCtrl::SelectAll )
			.def( "ClearText" , &XEditCtrl::ClearText )
			.def( "Copy" , &XEditCtrl::CopyToClipboard )
			.def( "Paste" , &XEditCtrl::PasteFromClipboard )
			// Events.
			.def( "SetOnText" , &_setOnTextWrap<XEditCtrl> )
			.def( "SetOnDefault" , &_setOnDefaultWrap<XEditCtrl> )
		;
		register_object_to_python<XEditCtrl>();

		class_< XTitle , Ref<XTitle> , bases< IGuiControl > , noncopyable >( "XTitle" , init<>() )
			.def( init<const WString&, const Rect<int>&>() )
			// Object property.
			.add_property( "text" , make_function( &XTitle::GetText , RET_COPYREF ) , &XTitle::SetText )
			.add_property( "style" , &_GetStyleWrap<XTitle> )
			// Methods.
		;
		register_object_to_python<XTitle>();

		class_< XImage , Ref<XImage> , bases< IGuiControl > , noncopyable >( "XImage" , init<>() )
			.def( init<IBitmap* , const Rect<int>&>() )
			// Object property.
			.add_property( "image" , &_getImageWrap<XImage> , &_setImageWrap<XImage> )
			.add_property( "style" , &_GetStyleWrap<XImage> )
			.add_property( "transparency" , &XImage::GetTransparency , &XImage::SetTransparency )
			// Methods.
			.def( "GetImage" , &_getImageWrap<XImage> )
			.def( "SetImage" , &_setImageWrap<XImage> )
			.def( "Rewind" , &XImage::Rewind )
			.def( "SetTransparency" , &XImage::SetTransparency )
		;
		register_object_to_python<XImage>();

		class_< XAnimation , Ref<XAnimation> , bases< IGuiControl > , noncopyable >( "XAnimation" , init<>() )
			.def( init<IBitmap* , const Rect<int>&>() )
			// Object property.
			.add_property( "image" , &_getImageWrap<XAnimation> , &_setImageWrap<XAnimation> )
			.add_property( "style" , &_GetStyleWrap<XAnimation> )
			.add_property( "speed" , &XAnimation::GetSpeed , &XAnimation::SetSpeed )
			.add_property( "transparency" , &XAnimation::GetTransparency , &XAnimation::SetTransparency )
			.add_property( "stopped" , &XAnimation::IsStopped )
			// Methods.
			.def( "GetImage" , &_getImageWrap<XAnimation> )
			.def( "SetImage" , &_setImageWrap<XAnimation> )
			.def( "SetSpeed" , &XAnimation::SetSpeed )
			.def( "GetSpeed" , &XAnimation::GetSpeed )
			.def( "SetPlayCount" , &XAnimation::SetPlayCount )
			.def( "GetPlayCount" , &XAnimation::GetPlayCount )
			.def( "SetTransparency" , &XAnimation::SetTransparency )
			.def( "GetTransparency" , &XAnimation::GetTransparency )
			.def( "IsStopped" , &XAnimation::IsStopped )
		;

		class_< XScrollBarVertical , bases< IScrollBarVertical > , noncopyable >( "XScrollBarVertical" , init<>() )
		;
		register_object_to_python< XScrollBarVertical >();

		class_< XDesktop , Ref<XDesktop> , bases< XForm > , noncopyable >( "XDesktop" , no_init )
			// Object property.
			.add_property( "size" , &XDesktop::GetDesktopSize )
			// Methods.
			.def( "GetDesktopSize" , &XDesktop::GetDesktopSize )
			.def( "Attach" , &XDesktopAttachWrap )
			.def( "Detach" , &XDesktopDetachWrap )
			.def( "ShowWindow" , &XDesktopShowWindowWrap1 )
			.def( "ShowWindow" , &XDesktopShowWindowWrap2 )
			.def( "TrackTips" , &XDesktopTrackTipsWrap )
			// Events.
		;
		register_object_to_python<XDesktop>();
	}

	namespace
	{
#define __declspec(X)

		BOOST_PYTHON_MODULE( xeres_comp )
		{
			expose_comp();
		}

#undef __declspec
	}

	// expose basic functions
	void expose_ui_to_python( RefWeak<XDesktop> desktop , ImageResource * image )
	{
		PythonPlug::instance().RegisterModule( "xeres" , init_module_xeres_comp );

		// Register desktop object.
		try
		{
			if( desktop.IsValid() )
			{
				PythonPlug::instance().RegisterObject( "xeres" , "desktop" ,
					object( Ref<XDesktop>( desktop ) ) );
			}

			if( image )
			{
				PythonPlug::instance().RegisterObject( "xeres" , "LoadImage" ,
					object( eternal_ptr<ImageResource>( image ) ) );
			}
		}
		catch ( boost::python::error_already_set )
		{
			PyErr_Print();
			PyErr_Clear();
		}
	}

} // namespace xeres
